查看原文
其他

后Kubernetes时代的微服务

听说过服务网格并试用过Istio的人可能都会有以下5个疑问

(1)为什么Istio 要绑定Kubernetes呢?

(2)Kubernetes和服务网格分别在云原生中扮演什么角色?

(3)Istio扩展了Kubernetes的哪些方面?解决了哪些问题?

(4)Kubernetes、xDS协议(Envoy、MOSN等)与Istio之间是什么关系?

(5)到底该不该使用Service Mesh?

本文将带读者梳理清楚 Kubernetes、xDS协议与Istio服务网格之间的内在联系。此外,本文还将介绍Kubernetes中的负载均衡方式,xDS协议对于服务网格的意义,以及为什么说即使有了Kubernetes还需要Istio。

使用服务网格并非与Kubernetes决裂,而是水到渠成的事情。Kubernetes的本质是通过声明配置对应用进行生命周期管理,而服务网格的本质是提供应用间的流量和安全性管理,以及可观察性。假如已经使用Kubernetes构建了稳定的微服务平台,那么如何设置服务间调用的负载均衡和流量控制?

Envoy创造的xDS协议被众多开源软件所支持,如Istio、Linkerd、MOSN等。Envoy对服务网格或云原生而言最大的贡献就是定义了xDS。Envoy本质上是一个网络代理,是通过API配置的现代版代理,基于它衍生出了很多不同的使用场景,如API 网关、服务网格中的Sidecar 代理和边缘代理。


01重要观点

如果想要提前了解下文的所有内容,可以先阅读下面列出的一些主要观点

  • Kubernetes的本质是应用的生命周期管理,具体来说,就是应用的部署和管理(扩缩容、自动恢复、发布)。

  • Kubernetes为微服务提供了可扩展、高弹性的部署和管理平台。

  • 服务网格的基础是透明代理,先通过Sidecar 代理拦截到微服务间流量,再通过控制平面配置管理微服务的行为。

  • 服务网格将流量管理从Kubernetes中解耦,服务网格内部的流量无须kube-proxy组件的支持,通过接近微服务应用层的抽象,管理服务间的流量,实现安全性和可观察性功能。

  • xDS定义了服务网格配置的协议标准。

  • 服务网格是对Kubernetes中的service更上层的抽象,它的下一步是serverless。


02Kubernetes与Service Mesh

1Kubernetes原生Service Mesh的服务访问关系(每个Pod部署一个Sidecar的模式)。

图1


流量转发

Kubernetes集群的每个节点都部署了一个kube-proxy组件,该组件会先与Kubernetes API Server通信,获取集群中的service信息,再设置iptables规则,直接将对某个service的请求发送到对应的Endpoint(属于同一组service的Pod)上。

服务发现

Istio服务网格不仅可以沿用Kubernetes中的service做服务注册,还可以通过控制平面的平台适配器对接其他服务发现系统,生成数据平面的配置(使用CRD声明,保存在etcd中)。数据平面的透明代理(Transparent Proxy)以Sidecar容器的形式部署在每个应用服务的Pod中,这些Proxy都需要请求控制平面同步代理配置。之所以说是透明代理,是因为应用程序容器完全没有感知代理的存在,在该过程中kube-proxy组件一样需要拦截流量,只不过kube-proxy组件拦截的是进出Kubernetes节点的流量,而Sidecar Proxy拦截的是进出该Pod的流量。图2所示为Istio中的服务发现机制。

图2

服务网格的劣势

由于Kubernetes的每个节点都会运行众多的Pod,因此将原先kube-proxy方式的路由转发功能置于每个Pod中,会导致大量的配置分发、同步和最终一致性问题。为了细粒度地进行流量管理,必须添加一系列新的抽象,从而导致用户的学习成本进一步增加,但随着技术的普及,该情况会慢慢得到缓解。

服务网格的优势

kube-proxy的设置都是全局生效的,无法对每个服务做细粒度的控制,而服务网格通过Sidecar Proxy的方式将Kubernetes中对流量的控制从service一层抽离出来,做更多的扩展。


03kube-proxy组件

在Kubernetes集群中,每个Node运行一个kube-proxy进程。kube-proxy负责为service实现一种VIP(虚拟IP地址)的形式。

在Kubernetes v1.0版本中,代理完全在userspace代理模式中实现。

在Kubernetes v1.1版本中,新增了iptables代理模式,但不是默认的运行模式。从Kubernetes v1.2版本起,默认使用iptables代理模式。在Kubernetes v1.8.0-beta.0版本中,添加了IPVS代理模式。

kube-proxy的缺陷

首先,如果转发的Pod不能正常提供服务,那么它不会自动尝试另一个Pod,不过这个问题可以通过liveness probes解决。每个Pod都有一个健康检查机制,当Pod健康状况有问题时,kube-proxy会删除对应的转发规则。另外,nodePort类型的服务也无法添加TLS,或者更复杂的报文路由机制。

kube-proxy实现了流量在Kubernetes 服务中多个Pod实例间的负载均衡,但是如何对这些服务间的流量做细粒度的控制,比如,将流量按照百分比划分到不同的应用版本(这些应用版本都属于同一个服务的一部分,但位于不同的部署上),做金丝雀发布(灰度发布)和蓝绿发布?Kubernetes社区给出了使用Deployment做金丝雀发布的方法,该方法本质上就是通过修改Pod的label将不同的Pod 划归到Deployment的service上。


04Kubernetes Ingress与Istio Gateway

kube-proxy只能路由Kubernetes集群内部的流量,而Kubernetes集群的Pod位于CNI创建的网络中,集群外部是无法直接与其通信的,因此在Kubernetes中创建了Ingress这个资源对象,并由位于Kubernetes边缘节点(这样的节点可以有很多个,也可以有一组)的Ingress Controller驱动,负责管理南北向流量。

Ingress必须对接各种Ingress Controller才能使用,比如,Nginx Ingress Controller、Traefik。Ingress只适用于HTTP流量,使用方式也很简单,但只能对service、Port、HTTP路径等有限字段匹配路由流量,这导致它无法路由如MySQL、Redis和各种私有RPC等TCP流量。

要想直接路由南北向的流量,只能使用service的LoadBalancer或NodePort,前者需要云厂商支持,后者需要进行额外的端口管理。

有些Ingress Controller支持暴露TCP和UDP服务,但是只能使用service来暴露,Ingress本身是不支持的,例如,Nginx Ingress Controller,服务暴露的端口是通过创建 ConfigMap的方式配置的。

Istio Gateway的功能与Kubernetes Ingress的功能类似,都是负责管理集群的南北向流量。

Istio Gateway可被看作网络的负载均衡器,用于承载进出网格边缘的连接。

Istio Gateway规范描述了一系列开放端口和这些端口所使用的协议、负载均衡的SNI配置等内容。

Istio 中的Gateway资源是一种CRD扩展,它同时复用了Sidecar 代理功能,详细配置请参考Istio官方网站。


05xDS协议

图3所示为Service Mesh的控制平面,读者在了解服务网格时可能看到过,每个方块代表一个服务的实例,例如,Kubernetes中的一个Pod(其中包含了Sidecar 代理)。xDS协议控制了Istio服务网格中所有流量的具体行为,即将图1-3中的方块链接到了一起。

图3

xDS协议是由Envoy提出的,在Envoy v2版本的API中最原始的xDS协议指的是CDS(Cluster Discovery Service)、EDS(Endpoint Discovery Service)、LDS(Listener Discovery Service)和RDS(Route Discovery Service),后来在Envoy v3版本中xDS协议又发展出了Scoped Route Discovery Service(SRDS)、Virtual Host Discovery Service(VHDS)、Secret Discovery Service(SDS)、Runtime Discovery Service(RTDS)。

下面通过两个服务的通信了解xDS协议,如图4所示。

图4

图4中的箭头不是流量进入Proxy后的路径或路由,也不是实际顺序,而是虚拟的一种xDS接口处理顺序。其实在各个xDS协议之间也是有交叉引用的。

支持xDS协议的代理可以通过查询文件或管理服务器动态发现资源。概括地讲,这些发现服务及其相应的API被称作xDS。Envoy通过订阅(Subscription)方式获取资源,订阅方式有以下3种。

  • 文件订阅:监控指定路径下的文件。发现动态资源的最简单方式就是将其保存于文件中,并将路径配置在configSource中的path参数中。

  • gRPC流式订阅:每个xDS API可以单独配置ApiConfigSource,指向对应的上游管理服务器的集群地址。

  • 轮询REST-JSON轮询订阅:单个xDS API可以对REST端点进行同步(长)轮询。

Istio使用gRPC流式订阅的方式配置所有的数据平面的Sidecar Proxy。下面总结关于xDS协议的要点。

  • CDS、EDS、LDS、RDS是最基础的xDS协议,都可以独立更新。

  • 所有的发现服务(Discovery Service)可以连接不同的管理服务,也就是说管理xDS的服务器可以有多个。

  • Envoy在原始xDS协议的基础上进行了一系列扩充,增加了SDS(密钥发现服务)、ADS(聚合发现服务)、HDS(健康发现服务)、MS(Metric服务)、RLS(速率限制服务)等API。

  • 为了保证数据一致性,若直接使用xDS原始API,则需要保证按照CDS → EDS → LDS → RDS的顺序更新。这是遵循电子工程中的先合后断(Make-Before-Break)原则的,即在断开原来的连接之前先建立好新的连接,应用在路由里就是为了防止在设置了新的路由规则时无法发现上游集群而导致流量被丢弃的情况,类似于电路里的断路。

  • CDS用于设置服务网格中有哪些服务。

  • EDS用于设置哪些实例(Endpoint)属于这些服务(Cluster)。

  • LDS用于设置实例上监听的端口以配置路由。

  • RDS是最终服务间的路由关系,应该保证最后更新RDS。


06Envoy

Envoy是Istio服务网格中默认的Sidecar,Istio在Envoy的基础上按照 Envoy的xDS协议扩展了其控制平面。在讲解Envoy xDS协议之前还需要先熟悉下Envoy的基本术语。下面列举了Envoy中的基本术语及其数据结构解析。

  • Downstream(下游):下游主机连接到Envoy,发送请求并接收响应,即发送请求的主机。

  • Upstream(上游):上游主机接收来自Envoy的连接和请求,并返回响应,即接收请求的主机。

  • Listener(监听器):监听器是命名网地址(例如,端口、UNIX Domain Socket等),下游客户端可以连接这些监听器。Envoy暴露一个或多个监听器给下游主机连接。

  • Cluster(集群):集群是指Envoy连接的一组逻辑相同的上游主机。Envoy通过服务发现来发现集群的成员,并且可以通过主动健康检查确定集群成员的健康状态。Envoy通过负载均衡策略决定将请求路由到集群的哪个成员。

Envoy中可以设置多个Listener,每个Listener中又可以设置filterchain(过滤器链表),而且过滤器是可扩展的,这样就可以更方便地操作流量了,例如,设置加密、私有RPC等。

xDS协议是由Envoy提出的,目前是Istio中默认的Sidecar 代理。但是,只要实现了xDS协议,理论上就可以作为Istio中的Sidecar 代理,例如,蚂蚁集团开源的MOSN。


07Istio Service Mesh

Istio是一个功能十分丰富的Service Mesh实现产品,包括如下功能。

  • 流量管理:这是Istio最基本的功能。

  • 策略控制:通过Mixer组件和各种适配器可以实现访问控制系统、遥测捕获、配额管理和计费等策略控制。

  • 可观测性:通过Mixer实现。

  • 安全认证:通过Citadel组件做密钥和证书管理。

Istio中定义了如下的CRD来帮助用户进行流量管理。

  • Gateway:描述了在网络边缘运行的负载均衡器,用于接收传入或传出的HTTP / TCP连接。

  • VirtualService:实际上可以将Kubernetes服务连接到Istio Gateway上,并且可以执行更多操作,例如,定义一组流量路由规则,以便在主机被寻址时应用。

  • DestinationRule:决定了经过路由处理之后的流量的访问策略。简单来说,就是定义流量如何路由。这些策略中可以定义负载均衡配置、连接池尺寸及外部检测(用于在负载均衡池中对不健康主机进行识别和驱逐)配置。

  • EnvoyFilter:描述了针对代理服务的过滤器,这些过滤器可以定制由Istio Pilot生成的代理配置。初级用户一般很少用到这个配置。

  • ServiceEntry:在默认情况下,Istio服务网格中的服务是无法发现Mesh以外的服务的。ServiceEntry能够在Istio内部的服务注册表中加入额外的条目,从而让服务网格中的服务能够访问和路由到这些被手动加入的服务。


08什么是Istio

通过前面的介绍,读者已经对Service Mesh已经有了初步的认识。Istio作为一个开源的Service Mesh实现产品,一经推出就备受瞩目,成为各大厂商和开发者争相追捧的对象。因此,Istio很有可能会成为继Kubernetes之后的又一个明星级产品。

Istio官方文档是这样定义的:

“它是一个完全开源的服务网格,以透明的方式构建在现有的分布式应用中。它也是一个平台,拥有可以集成任何日志、遥测和策略系统的API接口。Istio多样化的特性使你能够成功且高效地运行分布式微服务架构,并提供保护、连接和监控微服务的统一方法。”

从官方定义可以看出,Istio提供了一种完整的解决方案,可以使用统一的方式管理和监测微服务应用。

同时,它具有管理流量、实施访问策略、收集数据等方面的功能,而且所有的这些都对应用透明,几乎不需要修改业务代码就能实现。

有了Istio,用户几乎可以不再使用其他的微服务框架,也不需要自己去实现服务治理等功能。只要把网络层委托给Istio,它就能帮用户完成这一系列的功能。

简单来说,Istio就是一个提供了服务治理功能的服务网格。


09为什么使用Istio

Service Mesh是一种服务治理技术,其核心功能是对流量进行控制。

从这一点来说,Service Mesh和现有的服务治理产品在功能上是有重合的。如果一个企业使用的微服务应用已经具有了非常完善的服务治理功能,则不一定非得引入Service Mesh。

但是,如果企业使用的系统不具有完善的治理功能,或者系统架构中的痛点正好可以被Service Mesh解决,则Service Mesh是最佳选择。

相对于基于公共库的服务治理产品,Service Mesh最大的特性就是对应用透明。用户不仅可以将自己的微服务应用无缝地接入网格,而且无须修改业务逻辑。目前Istio提供了以下4个重要的功能。

  • 为HTTP、gRPC、WebSocket和TCP流量自动负载均衡。

  • 通过丰富的路由规则、重试、故障转移和故障注入对流量行为进行细粒度控制。

  • 提供完善的可观察性方面的功能,包括对所有网格控制下的流量进行自动化度量、日志记录和追踪。

  • 提供身份认证和授权策略,在集群中实现安全的服务间通信。


10Istio的平台支持

Istio独立于平台,被设计为可以在各种环境中运行,包括跨云、内部环境、Kubernetes等。目前Istio支持的平台有:

(1)部署在Kubernetes集群的服务。

(2)在Consul中注册的服务。

(3)在独立的虚拟机中运行的服务。

本文节选自《深入理解Istio:云原生服务网格进阶实战》一书,欢迎阅读此书了解更多相关内容!


 

如果喜欢本文欢迎 在看留言分享至朋友圈 三连
继续滑动看下一个
中生代技术
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存